/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.huangp.web;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import net.huangp.dao.TransactionDAO;
import net.huangp.domain.SMS;
import net.huangp.exception.SMSCSVParsingException;
import net.huangp.exception.SMSNotFoundException;
import net.huangp.framework.PageBasicImpl;
import net.huangp.jms.JmsProducer;
import net.huangp.service.SMSService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

/**
 *
 * @author Patrick Huang
 */
@Controller
public class SMSController {
    //--------------------------------------------------------------------------
    // Static Properties
    //--------------------------------------------------------------------------
    private Logger logger = LoggerFactory.getLogger(SMSController.class);
    private static final File tempDir = new File(System.getProperty("java.io.tmpdir"));
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    //--------------------------------------------------------------------------
    // Properties
    //--------------------------------------------------------------------------
    @Autowired
    private SMSService smsService;
    
    /**
     * TODO dependancy injection?
     */
    private Integer defaultPageSize = 20;
    // -------------------------------------------------------------------------
    // Implementation Methods
    // -------------------------------------------------------------------------
    /**
     * update csv sms file form
     * @return csv file upload form view
     */
    @RequestMapping(value="/upload.html",method=RequestMethod.GET)
    public String smsUploadForm(){
        logger.debug("show form");
        return "smsForm";
    }

    /**
     * process uploaded csv sms file
     * @param csvFile
     * @param model
     * @return csv file upload result view
     * @throws Exception
     */
    @RequestMapping(value="/upload.html",method=RequestMethod.POST)
    public String smsUploadProcess(@RequestParam("csvFile") MultipartFile csvFile,
            ModelMap model) throws Exception{

        final File file = new File(tempDir,new Date().getTime() + ".csv");
        logger.debug("about to transfer to [{}]",file.getAbsolutePath());
        csvFile.transferTo(file);
        //use another thread to do background work.
        Long tranId = this.smsService.backgroundProcessCSV(file);
        model.addAttribute("transactionId", tranId);
        return "processing";
    }

    /**
     * list sms in a paginated way
     * @param start start position of the list. Default 0.
     * @param max number of sms per page. Default is DefaultPageSize.
     * @param model
     * @return
     */
    @RequestMapping("/list.html")
    public String smsList(@RequestParam(value="start",defaultValue="0") int start,
            @RequestParam(value="max",required=false) Integer max,ModelMap model){
        //set start and max
        if(start < 0){
            start = 0;
        }
        if(max == null){
            max = defaultPageSize;
        }
        List<SMS> smsList = this.smsService.listSMS(start,max);
        model.addAttribute("list", smsList);

        //pagination
        //entire list size
        long total = this.smsService.countSMS();
        PageBasicImpl page = new PageBasicImpl(start, max, total-1);
        model.addAttribute("page", page);
        
        return "smsList";
    }

    /**
     * search sms by providing optional fields.
     * Empty string will be converted to null.
     * @param sender
     * @param receiver
     * @param message
     * @param smsDate
     * @param model
     * @return
     */
    @RequestMapping("/search.html")
    public String smsSearch(@RequestParam(value="sender",required=false) String sender,
            @RequestParam(value="receiver",required=false) String receiver,
            @RequestParam(value="message",required=false) String message,
            @RequestParam(value="smsDate",required=false) Date smsDate,
            ModelMap model){
        //set up search criteria
        SMS exampleSms = new SMS();
        exampleSms.setSender(sender);
        exampleSms.setReceiver(receiver);
        exampleSms.setMessage(message);
        exampleSms.setSmsDate(smsDate);

        List<SMS> result = this.smsService.searchSMSByExample(exampleSms);
        model.addAttribute("list", result);
        return "smsList";
    }

    @InitBinder
    public void initBinder(WebDataBinder binder){
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
        dateFormat.setLenient(false);
        //allowEmpty is set to true so empty string will be interpreted as null
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }

    @ExceptionHandler({SMSNotFoundException.class,SMSCSVParsingException.class})
    public String handleException(Exception e,ModelMap model){
        model.addAttribute("exception", e);
        return "error";
    }
    // -------------------------------------------------------------------------
    // Mutator Methods
    // -------------------------------------------------------------------------
    public void setSmsService(SMSService smsService) {
        this.smsService = smsService;
    }
}
